package com.example.wordgenerator;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class WordGenerator extends JFrame {
    private static final long serialVersionUID = 1L;

    private JFileChooser fileChooser = new JFileChooser();
    private JLabel templateLabel = new JLabel("模板文件：");
    private JLabel excelLabel = new JLabel("Excel文件：");
    private JLabel saveDirLabel = new JLabel("保存目录：");
    private JButton templateButton = new JButton("选择模板");
    private JButton excelButton = new JButton("选择Excel");
    private JButton saveDirButton = new JButton("选择目录");
    private JButton generateButton = new JButton("生成文档"); // 确保按钮已声明
    private DefaultTableModel tableModel = new DefaultTableModel();
    private JTable mappingTable = new JTable(tableModel);
    private JScrollPane tableScrollPane = new JScrollPane(mappingTable);
    private File templateFile;
    private File excelFile;
    private File saveDir; // 新增保存目录

    private JTextField fileNameTemplateField = new JTextField("output_{Date}.docx", 25);
    private JTextField saveDirField = new JTextField(25); // 新增保存目录显示文本框
    private JTextArea helpText = new JTextArea( // 新增帮助说明区域
            "【模板使用说明】\n" +
                    "1. 模板文件中的占位符格式：\n" +
                    "   • ${列名}：替换为Excel对应列的值（如：${姓名}、${电话}）\n" +
                    "   • {Date:格式}：生成当前日期（格式参考：yyyy-MM-dd 或 HHmmss）\n" +
                    "   • 示例：\"报告_${姓名}_{Date:yyyyMMdd}.docx\"\n\n" +

                    "2. 文件名模板规则：\n" +
                    "   • 支持列名占位符（如：${姓名}）和日期占位符（如：{Date:yyyy-MM-dd}）\n" +
                    "   • 默认扩展名为.docx，可自定义（如：.pdf需自行修改）\n\n" +

                    "3. 生成流程：\n" +
                    "   1. 选择Word模板文件\n" +
                    "   2. 选择Excel数据文件\n" +
                    "   3. 映射模板占位符到Excel列名\n" +
                    "   4. 配置文件名模板\n" +
                    "   5. 点击生成文档\n\n" +

                    "4. 注意事项：\n" +
                    "   • 保存目录未选择时，默认保存到Excel文件所在目录\n" +
                    "   • 确保Excel第一行是列名，且无空值\n" +
                    "   • 日期格式需符合Java SimpleDateFormat规范", 12, 30);

    private Map<String, String> placeholderMapping = new HashMap<>();

    public WordGenerator() {
        initUI();
    }

    private void initUI() {
        setTitle("Word文档生成工具");
        setSize(950, 700);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        // 控制面板使用垂直布局
        JPanel controlPanel = new JPanel(new BorderLayout(10, 10));
        controlPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        // 左侧文件选择区域
        JPanel filePanel = new JPanel(new GridLayout(0, 2, 5, 5));
        filePanel.setBorder(BorderFactory.createTitledBorder("文件选择"));

        filePanel.add(templateLabel);
        filePanel.add(templateButton);
        filePanel.add(excelLabel);
        filePanel.add(excelButton);
        filePanel.add(saveDirLabel);
        filePanel.add(saveDirField);
        filePanel.add(new JLabel()); // 空占位符
        filePanel.add(saveDirButton);

        // 右侧文件名模板区域
        JPanel fileNamePanel = new JPanel(new BorderLayout());
        fileNamePanel.setBorder(BorderFactory.createTitledBorder("文件名模板"));
        fileNamePanel.add(new JLabel("模板："), BorderLayout.NORTH);
        fileNamePanel.add(fileNameTemplateField, BorderLayout.CENTER);

        // 底部按钮区域
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        buttonPanel.add(generateButton);

        // 组合控制面板
        controlPanel.add(filePanel, BorderLayout.NORTH);
        controlPanel.add(fileNamePanel, BorderLayout.CENTER);
        controlPanel.add(buttonPanel, BorderLayout.SOUTH);

        // 主界面布局
        add(controlPanel, BorderLayout.NORTH);
        add(new JScrollPane(mappingTable), BorderLayout.CENTER);
        add(new JScrollPane(helpText), BorderLayout.SOUTH);

        // 初始化表格
        tableModel.addColumn("模板占位符");
        tableModel.addColumn("Excel列名");

        // 按钮事件绑定
        templateButton.addActionListener(e -> chooseTemplate());
        excelButton.addActionListener(e -> chooseExcel());
        saveDirButton.addActionListener(e -> chooseSaveDir());
        generateButton.addActionListener(e -> generateDocuments());

        // 禁用文本框
        saveDirField.setEditable(false);
        helpText.setEditable(false);
        helpText.setLineWrap(true);
        helpText.setBackground(getBackground());

        setVisible(true);
    }

    // 选择模板
    private void chooseTemplate() {
        fileChooser.setFileFilter(new FileNameExtensionFilter("Word文档", "docx"));
        if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
            templateFile = fileChooser.getSelectedFile();
            templateLabel.setText("模板文件：" + templateFile.getName());
            loadTemplatePlaceholders();
        }
    }

    // 选择Excel
    private void chooseExcel() {
        fileChooser.setFileFilter(new FileNameExtensionFilter("Excel文件", "xlsx"));
        if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
            excelFile = fileChooser.getSelectedFile();
            excelLabel.setText("Excel文件：" + excelFile.getName());
            loadExcelColumns();
        }
    }

    // 选择保存目录
    private void chooseSaveDir() {
        fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        if (fileChooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
            saveDir = fileChooser.getSelectedFile();
            saveDirField.setText(saveDir.getAbsolutePath());
        }
    }

    // 加载模板占位符
    private void loadTemplatePlaceholders() {
        try (FileInputStream fis = new FileInputStream(templateFile)) {
            XWPFDocument doc = new XWPFDocument(fis);
            List<String> placeholders = new ArrayList<>();

            for (XWPFParagraph paragraph : doc.getParagraphs()) {
                Matcher matcher = Pattern.compile("\\$\\{([^}]+)\\}").matcher(paragraph.getText());
                while (matcher.find()) {
                    String placeholder = matcher.group(1);
                    if (!placeholders.contains(placeholder)) {
                        placeholders.add(placeholder);
                    }
                }
            }

            tableModel.setRowCount(0);
            for (String placeholder : placeholders) {
                tableModel.addRow(new Object[]{placeholder, ""});
            }

            generateButton.setEnabled(excelFile != null && tableModel.getRowCount() > 0);
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, "读取模板失败：" + ex.getMessage());
        }
    }

    // 加载Excel列
    private void loadExcelColumns() {
        try (FileInputStream fis = new FileInputStream(excelFile)) {
            Workbook workbook = new XSSFWorkbook(fis);
            Sheet sheet = workbook.getSheetAt(0);
            Row headerRow = sheet.getRow(0);
            if (headerRow == null) {
                JOptionPane.showMessageDialog(this, "Excel文件第一行未找到列名！");
                return;
            }

            List<String> columns = new ArrayList<>();
            for (int i = 0; i < headerRow.getLastCellNum(); i++) {
                Cell cell = headerRow.getCell(i);
                columns.add(cell.getStringCellValue());
            }

            DefaultCellEditor editor = new DefaultCellEditor(new JComboBox<>(columns.toArray(new String[0])));
            mappingTable.getColumnModel().getColumn(1).setCellEditor(editor);

            generateButton.setEnabled(templateFile != null && excelFile != null && tableModel.getRowCount() > 0);
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, "读取Excel失败：" + ex.getMessage());
        }
    }

    // 生成文档
    private void generateDocuments() {
        if (templateFile == null || excelFile == null) {
            JOptionPane.showMessageDialog(this, "请先选择模板和Excel文件！");
            return;
        }

        placeholderMapping.clear();
        for (int i = 0; i < tableModel.getRowCount(); i++) {
            String placeholder = (String) tableModel.getValueAt(i, 0);
            String excelColumn = (String) tableModel.getValueAt(i, 1);
            if (excelColumn != null && !excelColumn.isEmpty()) {
                placeholderMapping.put(placeholder, excelColumn);
            }
        }

        if (placeholderMapping.isEmpty()) {
            JOptionPane.showMessageDialog(this, "请完成占位符与Excel列的映射！");
            return;
        }

        try {
            List<Map<String, String>> dataRows = readExcelData();
            String parent = saveDir != null ? saveDir.getAbsolutePath() : excelFile.getParent();
            List<String> generatedFiles = new ArrayList<>();

            String fileNameTemplate = fileNameTemplateField.getText().trim();
            if (fileNameTemplate.isEmpty()) {
                fileNameTemplate = "output_{Date}.docx";
            }

            for (Map<String, String> row : dataRows) {
                String fileName = fileNameTemplate;

                // 替换列名占位符
                for (Map.Entry<String, String> entry : row.entrySet()) {
                    String placeholder = "${" + entry.getKey() + "}";
                    fileName = fileName.replace(placeholder, entry.getValue());
                }

                // 替换日期占位符
                Pattern datePattern = Pattern.compile("\\{Date(?::([^}]+))?\\}");
                Matcher dateMatcher = datePattern.matcher(fileName);
                StringBuffer sb = new StringBuffer();
                while (dateMatcher.find()) {
                    String format = dateMatcher.group(1);
                    String dateFormat = format != null ? format : "yyyy-MM-dd";
                    String replacement = new SimpleDateFormat(dateFormat).format(new Date());
                    dateMatcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
                }
                dateMatcher.appendTail(sb);
                fileName = sb.toString();

                // 确保扩展名正确
                if (!fileName.endsWith(".docx")) {
                    fileName += ".docx";
                }

                String filePath = new File(parent, fileName).getAbsolutePath();

                try (FileInputStream templateFis = new FileInputStream(templateFile)) {
                    XWPFDocument doc = new XWPFDocument(templateFis);
                    Map<String, String> data = new HashMap<>();
                    for (Map.Entry<String, String> entry : placeholderMapping.entrySet()) {
                        String placeholder = entry.getKey();
                        String excelColumn = entry.getValue();
                        String value = row.get(excelColumn);
                        if (value != null) {
                            data.put(placeholder, value);
                        }
                    }
                    replacePlaceholders(doc, data);

                    try (FileOutputStream fos = new FileOutputStream(filePath)) {
                        doc.write(fos);
                    }
                    generatedFiles.add(filePath);
                }
            }

            // 提示生成结果
            String message = "文档生成完成！共生成" + dataRows.size() + "份文件，保存在：" + parent + "\n文件列表：\n" + String.join("\n", generatedFiles);
            JOptionPane.showMessageDialog(this, message);
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, "生成失败：" + ex.getMessage());
        }
    }

    // 替换模板中的占位符
    private void replacePlaceholders(XWPFDocument doc, Map<String, String> data) {
        for (XWPFParagraph paragraph : doc.getParagraphs()) {
            List<XWPFRun> runs = paragraph.getRuns();
            if (runs == null || runs.isEmpty()) continue;
            for (XWPFRun run : runs) {
                String text = run.getText(0);
                if (text == null) continue;
                for (Map.Entry<String, String> entry : data.entrySet()) {
                    String placeholder = "${" + entry.getKey() + "}";
                    if (text.contains(placeholder)) {
                        text = text.replace(placeholder, entry.getValue());
                    }
                }
                run.setText(text, 0);
            }
        }
    }

    // 读取Excel数据
    private List<Map<String, String>> readExcelData() throws IOException {
        List<Map<String, String>> dataRows = new ArrayList<>();
        try (FileInputStream fis = new FileInputStream(excelFile)) {
            Workbook workbook = new XSSFWorkbook(fis);
            Sheet sheet = workbook.getSheetAt(0);
            Map<String, Integer> columnIndexes = new HashMap<>();

            Row headerRow = sheet.getRow(0);
            for (int i = 0; i < headerRow.getLastCellNum(); i++) {
                Cell cell = headerRow.getCell(i);
                columnIndexes.put(cell.getStringCellValue(), i);
            }

            Iterator<Row> rowIterator = sheet.iterator();
            while (rowIterator.hasNext()) {
                Row row = rowIterator.next();
                if (row.getRowNum() == 0) continue;
                Map<String, String> rowData = new HashMap<>();
                for (Map.Entry<String, Integer> entry : columnIndexes.entrySet()) {
                    Cell cell = row.getCell(entry.getValue());
                    rowData.put(entry.getKey(), getCellValue(cell));
                }
                dataRows.add(rowData);
            }
        }
        return dataRows;
    }

    // 获取单元格值
    private String getCellValue(Cell cell) {
        if (cell == null) return "";
        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                return String.valueOf(cell.getNumericCellValue());
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            default:
                return "";
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new WordGenerator());
    }
}